<template>
    <div class="standard-table">
      <el-card class="search-card">
        <search-form
          v-if="formOptions"
          ref="searchForm"
          :forms="formOptions.forms"
          :inline="formOptions.inline"
          :label-width="formOptions.labelWidth"
          :handle-search="searchHandler"
          :search-loading="loading"
          :showResetBtn="formOptions.showResetBtn"
          :searchBtnText="formOptions.searchBtnText"
          :resetBtnText="formOptions.resetBtnText"
          :handle-reset="formOptions.resetBtnCallback" />
      </el-card>

      <el-card class="table-card">
        <el-row class="table-toolbar" justify="space-between">
          <el-col :xs="24" :sm="12" :md="12" :lg="18" :xl="18">
            <div class="table-title">
              {{ title }}
            </div>
          </el-col>
          <el-col :xs="24" :sm="12" :md="12" :lg="6" :xl="6">
            <div class="table-toolbar-actions">
              <slot name="toolbar-actions"></slot>
              <el-button
                type="primary"
                size="small"
                v-if="!hiddenCreateBtn"
                @click="handleCreate"
              >
              <i class="el-icon-plus" />
              新增
            </el-button>
            </div>
          </el-col>
        </el-row>
        <el-table v-loading.lock="loading"
          ref="table"
          :data="tableData"
          :border="border"
          :size="size"
          :stripe="stripe"
          :height="height"
          :max-height="maxHeight"
          :fit="fit"
          :show-header="showHeader"
          :highlight-current-row="highlightCurrentRow"
          :current-row-key="currentRowKey"
          :row-class-name="rowClassName"
          :row-style="rowStyle"
          :row-key="rowKey"
          :empty-text="emptyText"
          :default-expand-all="defaultExpandAll"
          :expand-row-keys="expandRowKeys"
          :default-sort="defaultSort"
          :tooltip-effect="tooltipEffect"
          :show-summary="showSummary"
          :sum-text="sumText"
          :summary-method="summaryMethod"
          :style="tableStyle"
          @select="(selection, row) => emitEventHandler('select', selection, row)"
          @select-all="selection => emitEventHandler('select-all', selection)"
          @selection-change="selection => emitEventHandler('selection-change', selection)"
          @cell-mouse-enter="(row, column, cell, event) => emitEventHandler('cell-mouse-enter', row, column, cell, event)"
          @cell-mouse-leave="(row, column, cell, event) => emitEventHandler('cell-mouse-leave', row, column, cell, event)"
          @cell-click="(row, column, cell, event) => emitEventHandler('cell-click', row, column, cell, event)"
          @cell-dblclick="(row, column, cell, event) => emitEventHandler('cell-dblclick', row, column, cell, event)"
          @row-click="(row, event, column) => emitEventHandler('row-click', row, event, column)"
          @row-dblclick="(row, event) => emitEventHandler('row-dblclick', row, event)"
          @row-contextmenu="(row, event) => emitEventHandler('row-contextmenu', row, event)"
          @header-click="(column, event) => emitEventHandler('header-click', column, event)"
          @sort-change="args => emitEventHandler('sort-change', args)"
          @filter-change="filters => emitEventHandler('filter-change', filters)"
          @current-change="(currentRow, oldCurrentRow) => emitEventHandler('current-change', currentRow, oldCurrentRow)"
          @header-dragend="(newWidth, oldWidth, column, event) => emitEventHandler('header-dragend', newWidth, oldWidth, column, event)"
          @expand-change="(row, expanded) => emitEventHandler('expand-change', row, expanded)" >

          <slot name="prepend" />

          <template v-for="(column, columnIndex) in columns">
            <el-table-column
              :key="columnIndex"
              :column-key="column.columnKey"
              :prop="column.prop"
              :label="column.label"
              :width="column.minWidth ? '-' : (column.width || 140)"
              :minWidth="column.minWidth || column.width || 140"
              :fixed="column.fixed"
              :render-header="column.renderHeader"
              :sortable="column.sortable"
              :sort-by="column.sortBy"
              :sort-method="column.method"
              :resizable="column.resizable"
              :formatter="column.formatter"
              :show-overflow-tooltip="column.showOverflowTooltip"
              :align="column.align"
              :header-align="column.headerAlign || column.align"
              :class-name="column.className"
              :label-class-name="column.labelClassName"
              :selectable="column.selectable"
              :reserve-selection="column.reserveSelection"
              :filters="column.filters"
              :filter-placement="column.filterPlacement"
              :filter-multiple="column.filterMultiple"
              :filter-method="column.filterMethod"
              :filtered-value="column.filteredValue"
              v-if="column.type === undefined">
              <template slot-scope="scope" :scope="newSlotScope ? 'scope' : false">
                <span v-if="column.filter">
                  {{ Vue.filter(column['filter'])(scope.row[column.prop]) }}
                </span>
                <span v-else-if="column.slotName">
                  <slot :name="column.slotName" :row="scope.row" :$index="scope.$index" />
                </span>
                <span v-else-if="column.render">
                  {{ column.render(scope.row) }}
                </span>
                <span v-else-if="column.formatter">
                  {{ column.formatter(scope.row, scope.column, scope.row[column.prop], scope.$index) }}
                </span>
                <span v-else>
                  {{ scope.row[column.prop] }}
                </span>
              </template>
            </el-table-column>
            <el-table-column v-bind="column" :key="columnIndex" v-else></el-table-column>
          </template>

          <slot name="append" />

        </el-table>

        <div v-if="showPagination"
          style="margin-top: 10px;text-align: right;">
          <el-pagination
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="pagination.pageIndex"
            :page-sizes="pageSizes"
            :page-size="pagination.pageSize"
            :layout="paginationLayout"
            :total="total">
          </el-pagination>
        </div>
      </el-card>
    </div>
</template>
<script lang="ts">
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
import SearchForm from '@/components/SearchForm/index.vue'
import { ElTable } from 'element-ui/types/table'

@Component({
  name: 'StandardSearchTable',
  components: {
    SearchForm
  }
})
export default class extends Vue {
    @Prop({ default: [20, 50, 100] }) private pageSizes!: Array<any>
    @Prop({ default: [] }) private columns!: Array<any>
    @Prop({ default: {} }) private formOptions!: Array<any>
    @Prop({ }) private fetch!: Function
    @Prop({ default: true }) private showPagination!: boolean
    @Prop({ default: 'list' }) private listField!: string
    @Prop({ default: 'total' }) private totalField!: string
    @Prop({ default: true }) private autoLoad!: boolean
    @Prop({ default: '查询列表' }) private title!: string
    @Prop({ }) private handleCreate!: Function
    @Prop({ default: false }) private hiddenCreateBtn!: boolean

    private loading = false
    private total = 0
    private tableData: any[] = []
    private searchFormData = {}
    private pagination = {
      pageIndex: 1,
      pageSize: (() => {
        const { pageSizes } = this
        if (pageSizes.length > 0) {
          return pageSizes[0]
        }
        return 20
      })()
    }

    private emitEventHandler(event: string, ...args: any[]) {
      this.$emit(event, ...args)
    }

    private get newSlotScope() {
      return Number(Vue.version.replace(/\./g, '')) >= 250
    }

    private fetchHandler() {
      this.loading = true
      const response = this.fetch(this.searchFormData, this.pagination)
      response.then((data: any) => {
        if (Array.isArray(data)) {
          this.tableData = data
          this.total = 0
        } else {
          this.tableData = data[this.listField]
          this.total = data[this.totalField]
        }
        this.loading = false
      }).catch((_: any) => {
        this.loading = false
        console.log(_)
      })
    }

    mounted() {
      // event: expand changed to `expand-change` in Element v2.x
      (this.$refs.table as ElTable).$on('expand', (row: any, expanded: any) => this.emitEventHandler('expand', row, expanded))
      const { autoLoad } = this
      if (autoLoad) this.fetchHandler()
    }

    private handleSizeChange(size: number) {
      this.pagination.pageSize = size
      this.fetchHandler()
    }

    private handleCurrentChange(pageIndex: number) {
      this.pagination.pageIndex = pageIndex
      this.fetchHandler()
    }

    private searchHandler(resetPageIndex = true) {
      if (resetPageIndex) {
        this.pagination.pageIndex = 1
      }
      this.fetchHandler()
    }

    public reload(resetPageIndex = false) {
      if (resetPageIndex) {
        this.pagination.pageIndex = 1
      }
      this.fetchHandler()
    }
}
</script>
<style lang="scss" scoped>
.standard-table {
  margin: 20px;
  .search-card {
    margin-bottom: 20px;
  }
}

.table-toolbar-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
}
</style>
